import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { UserModule } from './user/user.module'
import { TypeOrmModule } from '@nestjs/typeorm'
import { TopicModule } from './topic/topic.module'
import { SubjectModule } from './subject/subject.module'
import { ExamModule } from './exam/exam.module'
import { LoggerMiddleware } from './middleware/login'
import { UploadModule } from './upload/upload.module'
import { RolesGuard } from './role/guard'
import { NoteModule } from './note/note.module'
import { TodolistModule } from './todolist/todolist.module'
import { AichatModule } from './aichat/aichat.module';

@Module({
  // imports 数组 用于导入其他模块，使当前模块可以使用这些模块提供的功能。
  imports: [
    UserModule,
    TypeOrmModule.forRoot({
      type: 'mysql', //数据库类型
      username: 'root', //账号
      password: 'yujian0923', //密码
      host: 'localhost', //host
      port: 13306, //
      database: 'exam', //库名
      synchronize: true, //synchronize字段代表是否自动将实体类同步到数据库
      retryDelay: 500, //重试连接数据库间隔
      retryAttempts: 10, //重试连接数据库的次数
      autoLoadEntities: true // autoLoadEntities: true 表示自动加载实体类。
    }),
    TopicModule,
    SubjectModule,
    ExamModule,
    UploadModule,
    NoteModule,
    TodolistModule,
    AichatModule
  ],
  controllers: [AppController],
  // providers 数组 列出当前模块提供的服务和其他提供者。
  providers: [
    AppService,
    //全局权限守卫
    // 是一个自定义的提供者，将 RolesGuard 注册为全局权限守卫，provide 是提供者的名称，useClass 是要使用的类。
    {
      provide: 'APP_GUARD',
      useClass: RolesGuard
    }
  ]
})

// 实现 NestModule 接口配置中间件
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      // LoggerMiddleware 中间件的作用是在请求处理过程中检查用户的登录状态
      .apply(LoggerMiddleware)
      // exclude 方法用于排除某些路由不应用中间件，这里排除了 user/login 和 user/logout 路由的所有请求方法。
      .exclude(
        {
          path: 'user/login',
          method: RequestMethod.ALL
        },
        {
          path: 'user/logout',
          method: RequestMethod.ALL
        },
        {
          path: 'user/register',
          method: RequestMethod.ALL
        }
      )
      // 将中间件应用到所有路由的所有请求方法。
      .forRoutes({
        path: '*',
        method: RequestMethod.ALL
      })
  }
}
